package com.erp.common.web;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.erp.app.common.ProjectConstants;
import com.erp.app.common.search.beans.SearchDelegate;
import com.erp.app.common.search.beans.SearchVO;
import com.erp.framework.controller.action.SimpleUserStyleAction;
import com.erp.framework.util.CommonUtil;
import com.erp.framework.util.CopyUtil;
import com.erp.framework.util.logger.Logger;

public class SearchAction extends SimpleUserStyleAction {

    protected String getModuleName(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response){
        return "";
    }
    
    protected String getMasterFormSessionName() {

        return "searchForm";
    }

    protected ActionForward handlePageEvent(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        return null;
    }
    
    protected ActionForward otherExecute(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response) throws ServletException {

        HttpSession session = request.getSession(false);
        
        SearchForm form = (SearchForm) formIn;
        String action = form.getPageEvent();
        action = (action == null) ? "" : action.trim();
        ActionForward actionForward = new ActionForward(mapping.getInput());
        ActionErrors errors = new ActionErrors();
        boolean handled = false;

        HashMap inParams = (HashMap) session.getAttribute(ProjectConstants.SESSION_COMMON_SEARCH_PARAMETERS);
        session.removeAttribute(ProjectConstants.SESSION_COMMON_SEARCH_PARAMETERS);

        Logger.debug(this, "otherExecute(), action = " + action + ", pageMode = " + form.getPageMode());
        Logger.debug(this, "otherExecute(), inParams is null?" + (inParams == null));

        if (inParams != null) {
            form = new SearchForm();

            // if AutoFill list is not specified, set it to all by default
            if (inParams.get(ProjectConstants.SESSION_SEARCH_CRITERIA_AUTOFILL_LIST) == null) {
                ArrayList autoFillList = new ArrayList();
                autoFillList.add("A");
                inParams.put(ProjectConstants.SESSION_SEARCH_CRITERIA_AUTOFILL_LIST, autoFillList);
            }

            form.setResizeTo(inParams.get(ProjectConstants.SESSION_SEARCH_CRITERIA_RESIZE_TO) != null ? (String[]) inParams
                    .get(ProjectConstants.SESSION_SEARCH_CRITERIA_RESIZE_TO) : new String[] { "750", "550" });

            form.setParams(inParams);
            form.setMultiRowClazz(SearchResultRow.class);
            session.setAttribute(getMasterFormSessionName(), form);
            setHandled(request);

            form.setIsExclusive(inParams.get(ProjectConstants.SESSION_EXCLUSIVE) != null);

            // for checking need to resize the window to default one.....
//            String needToResize = CommonUtil.nullToString(session.getAttribute(ProjectConstants.SESSION_INSPECTOR_REPORT_NEW));
//            session.removeAttribute(ProjectConstants.SESSION_INSPECTOR_REPORT_NEW);
//
//            if (needToResize != null && needToResize.equals(ProjectConstants.GENERIC_YES)) {
//                form.setNeedResize(ProjectConstants.GENERIC_YES);
//            }

            if (inParams.get(ProjectConstants.SESSION_AUTO_SEARCH) != null) {
                String autoSearch = (String) inParams.get(ProjectConstants.SESSION_AUTO_SEARCH);
                if ((null != autoSearch) && (ProjectConstants.GENERIC_YES.equals(autoSearch))) {                
                    form.setAutoSearch(true);
                } else {
                    form.setAutoSearch(false);
                }
            }

            if (inParams.get(ProjectConstants.SESSION_SHOW_FROM_TO) != null) {
                String showFromTo = (String) inParams.get(ProjectConstants.SESSION_SHOW_FROM_TO);
                if ((null != showFromTo) && (ProjectConstants.GENERIC_YES.equals(showFromTo))) {                
                    form.setShowFromTo(true);
                } else {
                    form.setShowFromTo(false);
                }
            }
            if (inParams.get(ProjectConstants.SESSION_SHOW_SEARCH_BTN) != null) {
                String showSearchBtn = (String) inParams.get(ProjectConstants.SESSION_SHOW_SEARCH_BTN);
                if ((null != showSearchBtn) && (ProjectConstants.GENERIC_YES.equals(showSearchBtn))) {                
                    form.setShowSearchBtn(true);
                } else {
                    form.setShowSearchBtn(false);
                }
            }
            if (inParams.get(ProjectConstants.SESSION_SHOW_OK_CANCEL_BTN) != null) {
                String showOkCancelBtn = (String) inParams.get(ProjectConstants.SESSION_SHOW_OK_CANCEL_BTN);
                if ((null != showOkCancelBtn) && (ProjectConstants.GENERIC_YES.equals(showOkCancelBtn))) {                
                    form.setShowOkCancelBtn(true);
                } else {
                    form.setShowOkCancelBtn(false);
                }
            }
            if (inParams.get(ProjectConstants.SESSION_SHOW_SELECT_BOX) != null) {
                String showSelectBox = (String) inParams.get(ProjectConstants.SESSION_SHOW_SELECT_BOX);
                if ((null != showSelectBox) && (ProjectConstants.GENERIC_YES.equals(showSelectBox))) {                
                    form.setShowSelectBox(true);
                } else {
                    form.setShowSelectBox(false);
                }
            }
            
            if (form.isAutoSearch()) {
                setHandled(request);
                setAutoSearchDefaultValues(form, inParams);
                actionForward = processActionSearch(mapping, form, request, response);
            } else {
                setSearchDefaultValues(form, inParams);
            }
        }

        if (!isHandled(request) && action.equalsIgnoreCase("ok")) {
            ArrayList selectedList = new ArrayList();
            ArrayList rows = form.getFinalRows();
            for (int i = 0; rows != null && i < rows.size(); i++) {
                SearchResultRow row = (SearchResultRow) rows.get(i);
                if (row.getIsDelete() != null && row.getIsDelete().length() > 1)
                    selectedList.add(row);
            }

            HashMap retParams = form.getParams();
            retParams.put(ProjectConstants.SESSION_SELECTED_LIST, selectedList);
            String sessionName = (String) retParams.get(ProjectConstants.SESSION_SESSION_NAME);
            String sessionValue = (String) retParams.get(ProjectConstants.SESSION_SESSION_VALUE);
            session.setAttribute(sessionName, sessionValue);
            session.setAttribute(ProjectConstants.SESSION_COMMON_SEARCH_PARAMETERS, retParams);
            setHandled(request);
        }

        if (!isHandled(request) && action.equalsIgnoreCase("selectAll")) {
            ArrayList selectedList = new ArrayList();
            ArrayList rows = form.getMultiRows(0);
            for (int i = 0; rows != null && i < rows.size(); i++) {
                SearchResultRow row = (SearchResultRow) rows.get(i);
                row.setIsDelete("checked");
            }
            setHandled(request);
        }

        if (!isHandled(request) && action.equalsIgnoreCase("deSelectAll")) {
            ArrayList selectedList = new ArrayList();
            ArrayList rows = form.getMultiRows(0);
            for (int i = 0; rows != null && i < rows.size(); i++) {
                SearchResultRow row = (SearchResultRow) rows.get(i);
                row.setIsDelete("");
            }
            setHandled(request);
        }

        if (!isHandled(request) && action.equalsIgnoreCase("search")) {
            setHandled(request);
            actionForward = processActionSearch(mapping, formIn, request, response);
        }

        if (!isHandled(request) && action.length() > 0) {
            Logger.all(this, "otherExecute(), action=" + action);
            actionForward = handlePageEvent(mapping, formIn, request, response, errors);
            setHandled(request);
        }
                
        saveErrors(request, errors);
        return actionForward;
    }

    private void setSearchDefaultValues(SearchForm form, HashMap inParams) {
        LinkedList criteriaList = (LinkedList) inParams.get(ProjectConstants.SESSION_CRITERIA_LIST);

        if (criteriaList != null) {
            Iterator iterator = criteriaList.iterator();
            int count = 0;
            while (iterator.hasNext()) {
                String fieldText = "";
                String fieldType = "";
                String fieldValue = "";

                if (iterator.hasNext()) {
                    fieldText = (String) iterator.next();
                }

                if (iterator.hasNext()) {
                    fieldType = (String) iterator.next();
                }

                if (iterator.hasNext()) {
                    fieldValue = (String) iterator.next();
                }

                if (fieldType == null) {
                    continue;
                }

                if ((fieldType.equals("HIDDEN")) || (fieldType.equals("DISPLAY"))) {
                    setField(form, count, fieldValue);
                    setFieldTo(form, count, fieldValue);
                } else if (fieldType.equals("COMBO"))
                    setField(form, count, fieldValue);
                count++;
            }
        }
    }

    private void setAutoSearchDefaultValues(SearchForm form, HashMap inParams) {

        LinkedList criteriaList = (LinkedList) inParams.get(ProjectConstants.SESSION_CRITERIA_LIST);

        if (criteriaList != null) {
            Iterator iterator = criteriaList.iterator();
            int count = 0;
            while (iterator.hasNext()) {
                String fieldText = "";
                String fieldType = "";
                String fieldValue = "";

                if (iterator.hasNext()) {
                    fieldText = (String) iterator.next();
                }

                if (iterator.hasNext()) {
                    fieldType = (String) iterator.next();
                }

                if (iterator.hasNext()) {
                    fieldValue = (String) iterator.next();
                }

                if (fieldType == null) {
                    continue;
                }

                if ((fieldType.equals("HIDDEN")) || (fieldType.equals("DISPLAY"))) {
                    setField(form, count, fieldValue);
                    setFieldTo(form, count, fieldValue);
                }
                count++;
            }
        }
    }

    private void setField(SearchForm form, int count, String value) {

        switch (count) {
            case 0:
                form.setField1(value);
                break;
            case 1:
                form.setField2(value);
                break;
            case 2:
                form.setField3(value);
                break;
            case 3:
                form.setField4(value);
                break;
            case 4:
                form.setField5(value);
                break;
            case 5:
                form.setField6(value);
                break;
            case 6:
                form.setField7(value);
                break;
            case 7:
                form.setField8(value);
                break;
            case 8:
                form.setField9(value);
                break;
            case 9:
                form.setField10(value);
                break;
            case 10:
                form.setField11(value);
                break;
            case 11:
                form.setField12(value);
                break;
            case 12:
                form.setField13(value);
                break;
            case 13:
                form.setField14(value);
                break;
            case 14:
                form.setField15(value);
                break;
            case 15:
                form.setField16(value);
                break;
            case 16:
                form.setField17(value);
                break;
            case 17:
                form.setField18(value);
                break;
            case 18:
                form.setField19(value);
                break;
            case 19:
                form.setField20(value);
                break;
        }
    }

    private void setFieldTo(SearchForm form, int count, String value) {

        switch (count) {
            case 0:
                form.setFieldTo1(value);
                break;
            case 1:
                form.setFieldTo2(value);
                break;
            case 2:
                form.setFieldTo3(value);
                break;
            case 3:
                form.setFieldTo4(value);
                break;
            case 4:
                form.setFieldTo5(value);
                break;
            case 5:
                form.setFieldTo6(value);
                break;
            case 6:
                form.setFieldTo7(value);
                break;
            case 7:
                form.setFieldTo8(value);
                break;
            case 8:
                form.setFieldTo9(value);
                break;
            case 9:
                form.setFieldTo10(value);
                break;
            case 10:
                form.setFieldTo11(value);
                break;
            case 11:
                form.setFieldTo12(value);
                break;
            case 12:
                form.setFieldTo13(value);
                break;
            case 13:
                form.setFieldTo14(value);
                break;
            case 14:
                form.setFieldTo15(value);
                break;
            case 15:
                form.setFieldTo16(value);
                break;
            case 16:
                form.setFieldTo17(value);
                break;
            case 17:
                form.setFieldTo18(value);
                break;
            case 18:
                form.setFieldTo19(value);
                break;
            case 19:
                form.setFieldTo20(value);
                break;
        }
    }

    protected ActionForward processActionSearch(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response) {

        ActionForward actionForward = null;
        try {
            SearchForm form = (SearchForm) formIn;
            actionForward = new ActionForward(mapping.getInput());
            HashMap params = form.getParams();
            ArrayList rsltColumnList = (ArrayList) params.get(ProjectConstants.SESSION_RESULT_COLUMN_LIST);
            boolean customColumnAlias = (ProjectConstants.GENERIC_YES.equals(params.get(ProjectConstants.SESSION_RESULT_CUSTOM_COLUMN_ALIAS)));
            if (rsltColumnList != null) {
                String columnStr = "";
                for (int i = 0; i < rsltColumnList.size(); i++) {
                    if (columnStr.length() > 0) {
                        columnStr += ",";
                    }
                    columnStr += rsltColumnList.get(i) + ((customColumnAlias) ? "" : (" COLUMN" + (i + 1)));
                }
                for (int i = rsltColumnList.size(); i < 50; i++) {
                    if (columnStr.length() > 0) {
                        columnStr += ",";
                    }
                    columnStr += "'' COLUMN" + (i + 1);
                }

                String criteriaStr = "";
                String tmpFrom = null;
                String tmpTo = null;
                Iterator criteriaIt = ((Collection) params.get(ProjectConstants.SESSION_CRITERIA_LIST)).iterator();
                ArrayList criteriaColumnList = (ArrayList) params.get(ProjectConstants.SESSION_CRITERIA_COLUMN_LIST);
                ArrayList criteriaColumnListProp = (ArrayList) params.get(ProjectConstants.SESSION_CRITERIA_COLUMN_PROP);
                SimpleDateFormat sdf = new SimpleDateFormat(CommonUtil.INPUT_DATE_FORMAT);

                for (int i = 0; criteriaColumnList != null && i < criteriaColumnList.size(); i++) {
                    if (CommonUtil.isEmpty(PropertyUtils.getSimpleProperty(form, "field" + (i + 1)))) {
                        tmpFrom = "";
                    } else {
                        tmpFrom = (String) PropertyUtils.getSimpleProperty(form, "field" + (i + 1));
                    }

                    if (CommonUtil.isEmpty(PropertyUtils.getSimpleProperty(form, "fieldTo" + (i + 1)))) {
                        tmpTo = "";
                    } else {
                        tmpTo = (String) PropertyUtils.getSimpleProperty(form, "fieldTo" + (i + 1));
                    }
                    tmpFrom = CommonUtil.stringRpl(tmpFrom, "'", "''");
                    tmpTo = CommonUtil.stringRpl(tmpTo, "'", "''");

                    String inputType = findCriteriaType(criteriaIt);

                    if (criteriaColumnListProp != null && criteriaColumnListProp.size() > 0) {
                        String columnProp = (String) criteriaColumnListProp.get(i);
                        if (!CommonUtil.isEmpty(columnProp)) {
                            if (columnProp.equals("DATE")) {
                                if (!CommonUtil.isEmpty(tmpFrom)) {
//                                    String dateMask = tmpFrom.indexOf("/") > -1 ? CommonUtil.DATE_WITH_SLASH_FORMAT_MASK
//                                            : CommonUtil.INPUT_DATE_FORMAT;
                                	String dateMask = CommonUtil.INPUT_DATE_FORMAT;
                                    criteriaStr += " AND " + criteriaColumnList.get(i) + " >= TO_DATE('"
                                            + CommonUtil.nullToString(tmpFrom).toUpperCase().trim() + "', '" + dateMask + "')";
                                }

                                if (!CommonUtil.isEmpty(tmpTo)) {
//                                    String dateMask = tmpTo.indexOf("/") > -1 ? CommonUtil.DATE_WITH_SLASH_FORMAT_MASK
//                                            : CommonUtil.INPUT_DATE_FORMAT;
                                	String dateMask = CommonUtil.INPUT_DATE_FORMAT;
                                    criteriaStr += " AND " + criteriaColumnList.get(i) + " <= TO_DATE('"
                                            + CommonUtil.nullToString(tmpTo).toUpperCase().trim() + "', '" + dateMask + "')";
                                }

                            } else if (columnProp.startsWith("SUB_QUERY")) {
                                String[] tmpAry = CommonUtil.split(columnProp, ":");
                                String tmp = "";
                                String field = tmpAry[1];

                                if (!CommonUtil.isEmpty(tmpFrom) || !CommonUtil.isEmpty(tmpTo)) {
                                    tmp = (String) criteriaColumnList.get(i);

                                    if (!CommonUtil.isEmpty(tmpFrom) && !CommonUtil.isEmpty(tmpTo)) {
                                        tmp = CommonUtil.stringRpl(tmp, "FROM?", field + " >= '"
                                                + CommonUtil.nullToString(tmpFrom).toUpperCase().trim() + "'");
                                        tmp = CommonUtil.stringRpl(tmp, "TO?", field + " <= '"
                                                + CommonUtil.nullToString(tmpTo).toUpperCase().trim() + "'");
                                    } else if (!CommonUtil.isEmpty(tmpFrom)) {
                                        tmp = CommonUtil.stringRpl(tmp, "FROM?", field + " >= '"
                                                + CommonUtil.nullToString(tmpFrom).toUpperCase().trim() + "'");
                                        tmp = CommonUtil.stringRpl(tmp, "AND TO?", "");
                                    } else if (!CommonUtil.isEmpty(tmpTo)) {
                                        tmp = CommonUtil.stringRpl(tmp, "TO?", field + " <= '"
                                                + CommonUtil.nullToString(tmpTo).toUpperCase().trim() + "'");
                                        tmp = CommonUtil.stringRpl(tmp, "FROM? AND", "");
                                    }

                                    criteriaStr += " AND " + tmp;

                                }

                            } else {
                                if (inputType.equals("INPUT_WITH_WILDCARD")) {
                                    if (!CommonUtil.isEmpty(tmpFrom))
                                        criteriaStr += " AND UPPER(" + criteriaColumnList.get(i) + ") LIKE '%"
                                                + CommonUtil.nullToString(tmpFrom).toUpperCase().trim() + "%'";
                                } else {
                                    if (!CommonUtil.isEmpty(tmpFrom))
                                        criteriaStr += " AND " + criteriaColumnList.get(i) + " >= '"
                                                + CommonUtil.nullToString(tmpFrom).toUpperCase().trim() + "'";
                                    if (!CommonUtil.isEmpty(tmpTo))
                                        criteriaStr += " AND " + criteriaColumnList.get(i) + " <= '"
                                                + CommonUtil.nullToString(tmpTo).toUpperCase().trim() + "'";
                                }
                            }
                        } else {
                            if (inputType.equals("INPUT_WITH_WILDCARD")) {
                                if (!CommonUtil.isEmpty(tmpFrom))
                                    criteriaStr += " AND UPPER(" + criteriaColumnList.get(i) + ") LIKE '%"
                                            + CommonUtil.nullToString(tmpFrom).toUpperCase().trim() + "%'";
                            } else {
                                if (!CommonUtil.isEmpty(tmpFrom))
                                    criteriaStr += " AND " + criteriaColumnList.get(i) + " >= '"
                                            + CommonUtil.nullToString(tmpFrom).toUpperCase().trim() + "'";
                                if (!CommonUtil.isEmpty(tmpTo))
                                    criteriaStr += " AND " + criteriaColumnList.get(i) + " <= '"
                                            + CommonUtil.nullToString(tmpTo).toUpperCase().trim() + "'";
                            }
                        }
                    } else {
                        if (inputType.equals("INPUT_WITH_WILDCARD")) {
                            if (!CommonUtil.isEmpty(tmpFrom))
                                criteriaStr += " AND UPPER(" + criteriaColumnList.get(i) + ") LIKE '%"
                                        + CommonUtil.nullToString(tmpFrom).toUpperCase().trim() + "%'";
                        } else {
                            if (!CommonUtil.isEmpty(tmpFrom))
                                criteriaStr += " AND " + criteriaColumnList.get(i) + " >= '"
                                        + CommonUtil.nullToString(tmpFrom).toUpperCase().trim() + "'";
                            if (!CommonUtil.isEmpty(tmpTo))
                                criteriaStr += " AND " + criteriaColumnList.get(i) + " <= '"
                                        + CommonUtil.nullToString(tmpTo).toUpperCase().trim() + "'";
                        }
                    }
                }

                Hashtable tblParams = (Hashtable) params.get(ProjectConstants.SESSION_TABLE_PARAMS);
                if (tblParams != null) {
                    String query = "SELECT "
                            + columnStr
                            + " FROM "
                            + tblParams.get(ProjectConstants.SESSION_TABLE)
                            + " WHERE 1=1"
                            + criteriaStr
                            + (CommonUtil.isEmpty(tblParams.get(ProjectConstants.SESSION_WHERE)) ? "" : " AND ("
                                    + tblParams.get(ProjectConstants.SESSION_WHERE) + ")")
                            + (CommonUtil.isEmpty(tblParams.get(ProjectConstants.SESSION_GROUPBY)) ? "" : " GROUP BY "
                                    + tblParams.get(ProjectConstants.SESSION_GROUPBY))
                            + (CommonUtil.isEmpty(tblParams.get(ProjectConstants.SESSION_ORDERBY)) ? "" : " ORDER BY "
                                    + tblParams.get(ProjectConstants.SESSION_ORDERBY));

                    Logger.debug(this, "otherExecute(), sql=" + query);
                    SearchDelegate dg = new SearchDelegate();
                    ArrayList details = dg.searchSearch(query);

                    form.getMultiRows().clear();
                    for (int i = 0; details != null && i < details.size(); i++) {
                        SearchResultRow row = new SearchResultRow();
                        SearchVO dtlVO = (SearchVO) details.get(i);
                        CopyUtil.convToStrObj(row, dtlVO);
                        row.setColumns(dtlVO.getColumns());
                        row.setIsDelete("");
                        form.setRow(i, row);
                    }
                }
            }
        } catch (Exception e) {
            Logger.error(this, "otherExecute(), error: " + e);
            if (Logger.isTraceLevel()) {
                e.printStackTrace();
            }
        }
        return actionForward;
    }

    private String findCriteriaType(Iterator it) {
        String type = "";

        // The following elements are common to all types
        it.next(); // 1st element of each type (Criteria label)
        type = (String) it.next();
        it.next(); // 3rd element of each type

        if (type.equals("HIDDEN")) {

        } else if (type.equals("DISPLAY")) {

        } else if (type.equals("INPUT")) {

        } else if (type.equals("COMBO")) {
            for (int i = 0; i < 6; i++)
                it.next();

        } else if (type.equals("COMBO_WITH_GROUP_BY")) {
            for (int i = 0; i < 7; i++)
                it.next();

        } else if (type.equals("COMBO_WITH_FROM_TO")) {
            for (int i = 0; i < 12; i++)
                it.next();

        } else if (type.equals("INPUT_WITH_WILDCARD")) {

        }

        return type;
    }
}